/**
 * @file usb_monitor.c
 * @brief 增强版USB存储设备监控（支持分区聚合和UUID获取）
 * @note 编译命令：gcc usb_monitor.c -o usb_monitor -ludev
 */
#include <libudev.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <poll.h>
#include <signal.h>
#include <errno.h>
#include <inttypes.h>
#include <stdbool.h>
//add by me
#include <sys/select.h>
/* According to earlier standards */
#include <sys/time.h>
#include <sys/types.h>
#include <time.h>
#include <libgen.h>
#include "usb_monitor.h"

//json 日志格式记录
#if 0
    1、接口插拔（手机、无线网卡设备接入 拔出 kafka审计日志）
    {
        "engine_id":    "1",             //引擎ID
        "engine_name":    "xxxx",        //引擎名称
        "interface_type":  0,            //接口类型: 网络接口0，串口接口1，kvm接口2， usb接口3（1手机、2无线网卡、3键盘、4鼠标、5、U盘）
        "interface_name":  "usb111",     //接口名称
        "usb_keyword":"xxxxx",           //usb外设唯一标识
        "usb_mount_dir": "/mnt/root",    //usb外设挂载点
        "desc": "接口属性信息"                 //一些能取到的接口信息，如usb存储大小信息，网口速率信息等。前端直接展示即可
        "start_time":     1665554263,    //事件时间
        "action": 0                      //动作：接入0， 拔出1
    }
#endif

static int g_exit_flag = 0;

void signal_handler(int sig) {
    g_exit_flag = 1;
}

/**
 * @brief 获取分区元数据（最终正确实现版）
 * @param part_dev 分区设备对象
 * @param p 分区信息结构体指针
 */
void get_partition_metadata(struct udev_device *part_dev, PartitionInfo *p) {
    // 初始化默认值
    strncpy(p->fs_type, UNKNOWN_INFO, sizeof(p->fs_type));
    strncpy(p->uuid, UNKNOWN_INFO, sizeof(p->uuid));
    strncpy(p->label, UNKNOWN_INFO, sizeof(p->label));

    /* 第一层：直接从设备属性获取 */
    const char *val = NULL;
    
    // 文件系统类型（优先级1：ID_FS_TYPE）
    if ((val = udev_device_get_property_value(part_dev, "ID_FS_TYPE"))) {
        strncpy(p->fs_type, val, sizeof(p->fs_type)-1);
    }
    // 文件系统类型（优先级2：分区表类型）
    else if ((val = udev_device_get_sysattr_value(part_dev, "partition/type"))) {
        strncpy(p->fs_type, val, sizeof(p->fs_type)-1);
    }

    /* 文件系统UUID（多层获取策略） */
    if ((val = udev_device_get_property_value(part_dev, "ID_FS_UUID"))) {
        strncpy(p->uuid, val, sizeof(p->uuid)-1);
    }
    else if ((val = udev_device_get_property_value(part_dev, "ID_FS_UUID_ENC"))) {
        strncpy(p->uuid, val, sizeof(p->uuid)-1);
    }

    /* 文件系统标签（多层获取策略） */
    if ((val = udev_device_get_property_value(part_dev, "ID_FS_LABEL"))) {
        strncpy(p->label, val, sizeof(p->label)-1);
    }
    else if ((val = udev_device_get_property_value(part_dev, "ID_FS_LABEL_ENC"))) {
        strncpy(p->label, val, sizeof(p->label)-1);
    }

    // 确保字符串正确终止
    p->fs_type[sizeof(p->fs_type)-1] = '\0';
    p->uuid[sizeof(p->uuid)-1] = '\0';
    p->label[sizeof(p->label)-1] = '\0';

    /* 特殊处理未格式化分区 */
    //0x83 是Linux原生分区类型标识
    //0x07是NTFS分区类型标识
    //当检测到这些类型但无文件系统时标记为UNFORMATTED
    if (strcmp(p->fs_type, "0x83") == 0 || 
        strcmp(p->fs_type, "0x07") == 0) {
        strncpy(p->fs_type, "UNFORMATTED", sizeof(p->fs_type)-1);
    }
}

/**
 * @brief 获取分区详细信息
 * @param udev udev上下文
 * @param parent 父设备（磁盘）
 * @param info 存储设备信息结构体指针
 */
void get_partitions_info(struct udev *udev, struct udev_device *parent, StorageInfo *info) {    
    struct udev_enumerate *enumerate = udev_enumerate_new(udev);
    if (!enumerate) {
        DEBUG(LOG_ERROR, "Failed to create udev enumerator");
        return ;
    }

    //这个函数有点问题，暂不使用
    //udev_enumerate_add_match_parent(enumerate, parent);
    
    //设置枚举器过滤器为"block"子系统
    udev_enumerate_add_match_subsystem(enumerate, "block");
    udev_enumerate_add_match_property(enumerate, "DEVTYPE", "partition");
    
    //用于扫描设备, 填充设备列表
    if(udev_enumerate_scan_devices(enumerate) < 0){
        udev_enumerate_unref(enumerate);
        DEBUG(LOG_ERROR, "udev_enumerate_scan_devices() error!");
        return;
    }

    struct udev_list_entry *devices = udev_enumerate_get_list_entry(enumerate); // 遍历设备列表
    if(!devices){
        udev_enumerate_unref(enumerate);
        DEBUG(LOG_ERROR, "udev_enumerate_get_list_entry() error!");
        return;
    }
    struct udev_list_entry *entry = NULL;
    
    info->partition_count = 0;
    udev_list_entry_foreach(entry, devices) {
        if(info->partition_count >= MAX_PARTITIONS){
            //最多获取8个分区的信息
            break;
        } 

        const char *path = udev_list_entry_get_name(entry);
        if(path != NULL && !strstr(path, info->sys_path)){
            //过滤跟父目录一样的路径，拿到同一个存储设备的分区信息, 如果不满足条件不处理
            continue;
        }
        
        struct udev_device *part_dev = udev_device_new_from_syspath(udev, path);
        if (!part_dev) {
            DEBUG(LOG_ERROR, "udev_device_new_from_syspath() error!");
            continue;
        }

        PartitionInfo *p = &info->partitions[info->partition_count];
        /* 获取基础信息 */
        snprintf(p->node, sizeof(p->node), "%s", udev_device_get_devnode(part_dev) ?: UNKNOWN_INFO);
        /* 获取容量信息 */
        const char *size_str = udev_device_get_sysattr_value(part_dev, "size");
        p->size = size_str ? strtoull(size_str, NULL, 10) * 512 : 0;

        /* 获取文件系统元数据（关键改进点） */
        get_partition_metadata(part_dev, p);

        info->partition_count ++;
        udev_device_unref(part_dev);
    }
    udev_enumerate_unref(enumerate);
}

void format_capacity(uint64_t bytes, char *buf, size_t buf_size) {
    const char *units[] = {"B", "KB", "MB", "GB", "TB"};
    int unit = 0;
    double size = bytes;

    while (size >= 1024 && unit < 4) {
        size /= 1024;
        unit++;
    }
    memset(buf, 0, buf_size);
    snprintf(buf, buf_size, "%.2f %s", size, units[unit]);
}

void print_usb_event_info_log(StorageInfo *info) {
    int i = 0;
    char total_size[32] = {0};

    //基础公共信息设置
    printf("===== USB Info =====\n");
    printf("engine_id: %s\n", info->engine_id);
    printf("engine_name: %s\n", info->engine_name);
    printf("interface_type: %d\n", info->interface_type);
    printf("interface_name: %s\n", info->interface_name);
    printf("usb_keyword: %s\n", info->usb_keyword);
    printf("usb_mount_dir: %s\n", info->usb_mount_dir);
    printf("start_time: %lu\n", time(NULL));
    printf("action: %u\n", info->action);

    //desc 信息
    printf("System Path:    %s\n", info->sys_path);
    if(strlen(info->vendor))
        printf("Vendor:         %s\n", info->vendor);
    if(strlen(info->vendor_id))
        printf("Vendor Id:      %s\n", info->vendor_id);
    if(strlen(info->model))
        printf("Model:          %s\n", info->model);
    if(strlen(info->model_id))
        printf("Model Id:       %s\n", info->model_id);
    if(strlen(info->dev_type))
        printf("Device Type:    %s\n", info->dev_type);

    //设备插入并且是存储设备
    if((info->action == 0) && strstr(info->dev_type, "disk")){
        format_capacity(info->total_size, total_size, sizeof(total_size));
        if(strlen(total_size))
            printf("Total Capacity: %s\n", total_size);
        printf("Partitions(%d):\n", info->partition_count);
        
        for (i = 0; i < info->partition_count; i++) {
            PartitionInfo *p = &info->partitions[i];
            char part_size[32];
            format_capacity(p->size, part_size, sizeof(part_size));
            
            printf("  [Partition %d]\n", i+1);
            printf("    Node:      %s\n", p->node);
            printf("    Size:      %s\n", part_size);
            printf("    FS Type:   %s\n", p->fs_type);
            printf("    UUID:      %s\n", p->uuid);
            printf("    Label:     %s\n", p->label);
        }
    }
    printf("==============================\n\n");
}

void printUsbEventInfoHdl(StorageInfo *info) {
    int i = 0;
    char total_size[32] = {0};

    //基础公共信息设置
    DEBUG(LOG_DEBUG, "===== USB Info ====");
    DEBUG(LOG_DEBUG,"engine_id: %s", info->engine_id);
    DEBUG(LOG_DEBUG,"engine_name: %s", info->engine_name);
    DEBUG(LOG_DEBUG,"interface_type: %d", info->interface_type);
    DEBUG(LOG_DEBUG,"interface_name: %s", info->interface_name);
    DEBUG(LOG_DEBUG,"usb_keyword: %s", info->usb_keyword);
    DEBUG(LOG_DEBUG,"usb_mount_dir: %s", info->usb_mount_dir);
    DEBUG(LOG_DEBUG,"start_time: %u", time(NULL));
    DEBUG(LOG_DEBUG,"action: %d", info->action);
    
    //desc 描述信息
    DEBUG(LOG_DEBUG,"System Path:    %s", info->sys_path);
    if(strlen(info->vendor))
        DEBUG(LOG_DEBUG,"Vendor:         %s", info->vendor);
    if(strlen(info->vendor_id))
        DEBUG(LOG_DEBUG,"Vendor Id:      %s", info->vendor_id);
    if(strlen(info->model))
        DEBUG(LOG_DEBUG,"Model:          %s", info->model);
    if(strlen(info->model_id))
        DEBUG(LOG_DEBUG,"Model Id:       %s", info->model_id);
    if(strlen(info->dev_type))
        DEBUG(LOG_DEBUG,"Device Type:    %s", info->dev_type);

    //设备插入并且是存储设备
    if((info->action == 0) && strstr(info->dev_type, "disk")){
        format_capacity(info->total_size, total_size, sizeof(total_size));
        
        if(strlen(total_size))
            DEBUG(LOG_DEBUG,"Total Capacity: %s", total_size);
        DEBUG(LOG_DEBUG,"Partitions(%d):", info->partition_count);
        
        for (i = 0; i < info->partition_count; i++) {
            PartitionInfo *p = &info->partitions[i];
            char part_size[32];
            format_capacity(p->size, part_size, sizeof(part_size));
            
            DEBUG(LOG_DEBUG,"  [Partition %d]", i+1);
            DEBUG(LOG_DEBUG,"    Node:      %s", p->node);
            DEBUG(LOG_DEBUG,"    Size:      %s", part_size);
            DEBUG(LOG_DEBUG,"    FS Type:   %s", p->fs_type);
            DEBUG(LOG_DEBUG,"    UUID:      %s", p->uuid);
            DEBUG(LOG_DEBUG,"    Label:     %s", p->label);
        }
    }
    DEBUG(LOG_DEBUG,"==============================");
}

/**
 * @brief usb设备插拔日志发送
 * @param dev udev设备对象， 设备消息结构体
 * @param 成功返回0， 失败-1
 */
void usb_event_log_json_send(StorageInfo *info)
{
    int i = 0;
    char size_buf[32] ={0};
    cJSON *pRoot = NULL;
    cJSON *part_info = NULL;     
    char part_size[32] = {0};
    char part_name[64];

    pRoot = cJSON_CreateObject();
    cJSON_AddStringToObject(pRoot, "engine_id", info->engine_id);           //引擎ID
    cJSON_AddStringToObject(pRoot, "engine_name", info->engine_name);       //引擎名称
    cJSON_AddNumberToObject(pRoot, "interface_type", info->interface_type); //usb接口 3   (1.手机 2.无线网卡 3.键盘 4.鼠标 5.U盘)                   
    cJSON_AddStringToObject(pRoot, "interface_name", info->interface_name); //物理端口信息，物理接口名称
    cJSON_AddStringToObject(pRoot, "usb_keyword", info->usb_keyword);       //外设唯一标识：序列号
    cJSON_AddStringToObject(pRoot, "usb_mount_dir", info->usb_mount_dir);   //usb外设挂载点
    cJSON_AddNumberToObject(pRoot, "start_time", time(NULL));               //事件时间
    cJSON_AddNumberToObject(pRoot, "action", info->action);                 // 动作：接入0， 拔出1
    
    //设置接口的特殊属性信息
    cJSON *desc = NULL; 
    desc = cJSON_CreateObject();
    if(strlen(info->dev_type))
        cJSON_AddStringToObject(desc, "dev_type", info->dev_type);
    if(strlen(info->vendor))
        cJSON_AddStringToObject(desc, "vendor", info->vendor);
    if(strlen(info->vendor_id))
        cJSON_AddStringToObject(desc, "vendor", info->vendor_id);
    if(strlen(info->model))
        cJSON_AddStringToObject(desc, "model", info->model);
    if(strlen(info->model_id))
        cJSON_AddStringToObject(desc, "model_id", info->model_id);
    if(strlen(info->sys_path))
        cJSON_AddStringToObject(desc, "sys_path", info->sys_path);
    

    //设备插入并且是存储设备
    if((info->action == 0) && strstr(info->dev_type, "disk")){
        format_capacity(info->total_size, size_buf, sizeof(size_buf));
        cJSON_AddStringToObject(desc, "disk_size", size_buf);
    
        if(info->partition_count > 0){
            cJSON_AddNumberToObject(desc, "partition_count", info->partition_count);
            for (i = 0; i < info->partition_count; i++) {
                PartitionInfo *p = &info->partitions[i];
                format_capacity(p->size, part_size, sizeof(part_size));        
                part_info = cJSON_CreateObject();
                memset(part_name, 0, sizeof(part_name));
                snprintf(part_name, sizeof(part_name), "[Partition %d]", i+1);
                cJSON_AddStringToObject(part_info, "Node",p->node);
                cJSON_AddStringToObject(part_info, "Size",part_size);                
                cJSON_AddStringToObject(part_info, "FS Type",p->fs_type);                
                cJSON_AddStringToObject(part_info, "UUID",p->uuid);                
                cJSON_AddStringToObject(part_info, "Label",p->label);
                cJSON_AddItemToObject(desc, part_name, part_info);
            } 
        }
    }
    cJSON_AddItemToObject(pRoot, "Desc", desc);

    char *data = cJSON_PrintUnformatted(pRoot);
    DEBUG(LOG_DEBUG, "data = \n%s\n", data);
    //send_data_to_logtype_kafka(TOPIC_LOG_FILE, NULL, 0, data, strlen(data));
    cJSON_Delete(pRoot);
}

/**
 * @brief 解析物理端口路径
 * @param dev udev设备对象
 * @param buffer 输出缓冲区
 * @param size 缓冲区大小
 */
void parse_physical_port(struct udev_device *dev, char *buffer, size_t size){
    const char *devpath = udev_device_get_devpath(dev);
    if(devpath != NULL){
        const char *usb_port_name = strstr(devpath, "usb");
        printf("parse_physical_port--devpath = [%s]\n", devpath);
        const char *usb_parm1 = "usb1/1-1";
        const char *usb_parm2 = "usb2/2-1";
        const char *usb_parm3 = "usb1/1-2";
        const char *usb_parm4 = "usb2/2-2";
        if(usb_port_name != NULL){
            if((strncmp(usb_port_name, usb_parm1, strlen(usb_parm1)) == 0) || (strncmp(usb_port_name, usb_parm2, strlen(usb_parm2)) == 0)){
                snprintf(buffer, size, "%s", "USB-1");
            }else if((strncmp(usb_port_name, usb_parm3, strlen(usb_parm3)) == 0) || (strncmp(usb_port_name, usb_parm4, strlen(usb_parm4)) == 0)){                    
                snprintf(buffer, size, "%s", "USB-2");
            }else{
                snprintf(buffer, size, usb_port_name);
            }
        }
        return ;
    }
    snprintf(buffer, size, UNKNOWN_INFO);
    return ;
}

/**
 * @brief 获取基础的公共属性信息
 */
int  getBasicCommonDeviceInfo(struct udev_device *dev, StorageInfo *info){
    //获取设备物理端口信息
    parse_physical_port(dev, info->interface_name, sizeof(info->interface_name));
        
    //获取设备节点信息
    snprintf(info->usb_mount_dir, sizeof(info->usb_mount_dir), "%s", udev_device_get_devnode(dev) ?: UNKNOWN_INFO);
    if(!strcmp(info->usb_mount_dir, UNKNOWN_INFO)){
        //如果DEVNode节点没挂载上，此时数据不完整，不处理该事件
        return -1;
    }else{
        printf("info->usb_devNode = [%s]\n", info->usb_mount_dir);
    }
    
    //获取设备所属系统路径
    snprintf(info->sys_path, sizeof(info->sys_path), "%s",udev_device_get_syspath(dev));

    //获取设备制造商信息          
    const char *model = udev_device_get_property_value(dev, "ID_MODEL");
    if(model){
        snprintf(info->model, sizeof(info->model), "%s", model);
    }
    const char *model_id = udev_device_get_property_value(dev, "ID_MODEL_ID");
    if(model_id){
        snprintf(info->model_id, sizeof(info->model_id), "%s", model_id);
    }
    
    //获取设备唯一标识
    const char *serial = udev_device_get_property_value(dev, "ID_SERIAL");
    if(serial){
        snprintf(info->usb_keyword, sizeof(info->usb_keyword), "%s", serial);
    }

    //获取供应商信息 
    const char *vendor = udev_device_get_property_value(dev, "ID_VENDOR");
    if(vendor){
        snprintf(info->vendor, sizeof(info->vendor), "%s", vendor);
    }
    const char *vendor_id = udev_device_get_property_value(dev, "ID_VENDOR_ID");
    if(vendor_id){
        snprintf(info->vendor_id, sizeof(info->vendor_id), "%s", vendor_id);
    }
    //const char *bus = udev_device_get_property_value(dev, "ID_BUS");
    //const char *revision = udev_device_get_property_value(dev, "ID_REVISION");
    
    return 0;
}

/**
 * @brief 获取设备所属类型
 * @param dev udev设备对象， 设备消息结构体
 * @param 成功返回0， 失败-1
 */
int getDeviceTypeInfo(struct udev_device *dev, StorageInfo *info) {
	const char *subsystem = udev_device_get_subsystem(dev);

    printf("getDeviceTypeInfo()-->subsystem = [%s]\n", subsystem);
	if(subsystem){
        if(strcmp(subsystem, "block") == 0){ //块设备事件(用于处理存储设备事件)
            const char *dev_idbus = udev_device_get_property_value(dev, "ID_BUS"); //获取总线类型  
            const char *dev_type = udev_device_get_property_value(dev, "DEVTYPE"); //获取设备类型
            printf("类型是:block-->[%s], dev_idbus = [%s]\n",dev_type, dev_idbus);
            if(dev_type){
				if(dev_idbus){
					if(strcmp(dev_idbus, "usb") == 0){          //USB总线设备: 如 U 盘、移动硬盘
						strncpy(info->dev_type, "USB disk", sizeof(info->dev_type)); 
					}else if(strcmp(dev_idbus, "scsi") == 0){   //SCSI总线设备: 如某些外部存储设备
						strncpy(info->dev_type, "SCSI disk", sizeof(info->dev_type));	
					}else if(strcmp(dev_idbus, "mmc") == 0){    //MMC/SD总线设备: 如 TF 卡
                        strncpy(info->dev_type, "MMC disk", sizeof(info->dev_type));
                    }else if(strcmp(dev_idbus, "ide") == 0){    //IDE总线设备: 如老式硬盘
                        strncpy(info->dev_type, "IDE disk", sizeof(info->dev_type));
                    }else if(strcmp(dev_idbus, "pci") == 0){    //PCI总线设备: 如内置硬盘
                        strncpy(info->dev_type, "PCI disk", sizeof(info->dev_type));
                    }else{
                        strncpy(info->dev_type, dev_type, sizeof(info->dev_type));
                    }
				}else{
					strncpy(info->dev_type, dev_type, sizeof(info->dev_type));
				}
            } else{
                    strncpy(info->dev_type, "block device", sizeof(info->dev_type));
            }
            return 0;
        }else if(strcmp(subsystem, "input") == 0) { // 输入设备
			const char *id_type = udev_device_get_property_value(dev, "ID_TYPE"); //获取输入设备类型
            printf("类型是:input-->[%s]\n", id_type);
            //输入设备类型‌：如键盘、鼠标、游戏手柄、触摸板、手写板等
            if(id_type){
                if(strcmp(id_type, "hid")== 0){
                    const char *dev_node = "/dev/input/event"; 
                    if(strstr(info->model, "Mouse") || strstr(info->model, "mouse")){ //带有Keyboard字样，说明是鼠标设备
                        const char *is_mouse = udev_device_get_property_value(dev, "ID_INPUT_MOUSE");            
                        if(is_mouse && strcmp(is_mouse, "1") == 0){
                            strncpy(info->dev_type, "Mouse", sizeof(info->dev_type));
                            if(strncmp(info->usb_mount_dir, dev_node, strlen(dev_node))){
                                //测试发现鼠标事件会上报两次，/dev/input/event, /dev/input/mouse0,过滤掉一次重复上报
                                return -1;
                            }
                        }else{
                            //该设备节点上报的数据信息不全，该次事件丢弃不处理
                            return -1;
                        }
                    }else if(strstr(info->model, "Keyboard") || strstr(info->model, "keyboard")){ //带有Keyboard字样，说明是键盘设备
                        const char *is_keyboard = udev_device_get_property_value(dev, "ID_INPUT_KEYBOARD");
                        if(is_keyboard && strcmp(is_keyboard, "1") == 0){
                            strncpy(info->dev_type, "Keyboard", sizeof(info->dev_type));
                        }else{
                            //该设备节点上报的数据信息不全，该次事件丢弃不处理
                            return -1;
                        }
                    }
                }else{
                   strncpy(info->dev_type, id_type, sizeof(info->dev_type)); 
                }
            }else{
                strncpy(info->dev_type, "input device", sizeof(info->dev_type)); 
            }
            return 0;
		} else if (strcmp(subsystem, "net") == 0) { // 以太网卡、Wi-Fi适配器
		    const char *name = udev_device_get_property_value(dev, "NAME");
            printf("类型是:net-->[%s]\n", name);
            DEBUG(LOG_DEBUG,"类型是:net-->[%s]", name);
            
			const char *interface = udev_device_get_property_value(dev, "INTERFACE");
			// 网络设备增强判断
			const char *driver = udev_device_get_property_value(dev, "ID_NET_DRIVER");
			if (driver){
				if (strcmp(driver, "iwlwifi") == 0) {
					strncpy(info->dev_type, "Intel Wireless", sizeof(info->dev_type));
				}else if (strcmp(driver, "ath9k") == 0) {
					strncpy(info->dev_type, "Atheros Wireless", sizeof(info->dev_type));
				}else{
					strncpy(info->dev_type, "Network Interface", sizeof(info->dev_type));
				}
			}else if(interface){
				if (strstr(interface, "wireless")){
					strncpy(info->dev_type, "Wireless NIC", sizeof(info->dev_type));
				}else{
					strncpy(info->dev_type, "Network Interface", sizeof(info->dev_type));
				}
			}else{
				strncpy(info->dev_type, "Network Interface", sizeof(info->dev_type));
			}
		} 		
	}else{
	    strncpy(info->dev_type, "Unknown", sizeof(info->dev_type));
    }
	return 0;
}

/**
 * @brief 获取存储设备元数据
 * @param dev udev设备对象
 * @param info 存储设备信息结构体
 */
void getUsbDiskStorageMetadata(struct udev_device *dev, StorageInfo *info) {
    struct udev *udev = udev_device_get_udev(dev);
    if(!udev){
        DEBUG(LOG_ERROR, "udev_device_get_udev() error!\n");
        return ;
    }
    // 磁盘容量信息
    const char *size_str = udev_device_get_sysattr_value(dev, "size");
    info->total_size = size_str ? strtoull(size_str, NULL, 10) * 512 : 0;

    // 获取分区详细信息
    get_partitions_info(udev, dev, info);
}

#if 0
// 解析接口信息
bool decode_usb_interface_auth(char *buf, StorageInfo *info)
{
    cJSON *root = NULL;
    cJSON *node = NULL;

    root = cJSON_Parse(buf);
    if (root == NULL)
    {
        DEBUG(LOG_ERROR, "parse buf to json failed!, errmsg=%s",
              cJSON_GetErrorPtr());
        return false;
    }

    node = cJSON_GetObjectItem(root, "engine_name");
    if ((node != NULL) && (node->valuestring != NULL))
    {
        if (strlen(node->valuestring) > 0)
        {
            snprintf(info->engine_name,
                     sizeof(info->engine_name), "%s",
                     node->valuestring);
        }
    }

    node = cJSON_GetObjectItem(root, "engine_id");
    if ((node != NULL) && (node->valuestring != NULL))
    {
        if (strlen(node->valuestring) > 0)
        {
            snprintf(info->engine_id,
                     sizeof(info->engine_id), "%s",
                     node->valuestring);
        }
    }

    cJSON_Delete(root);
    root = NULL;

    return true;
}

// 从json加载开关信息:获取引擎信息
// /opt/app/ics-agent/sync/engineSync/interface_auth.json
bool load_usb_interface_info(StorageInfo *info)
{
    FILE *fp = NULL;
    char *buf = NULL;
    size_t len = 0;

    len = get_file_size(FILENAME_USB_INTERFACE);
    if (len == 0)
    {
        DEBUG(LOG_ERROR, "filename:%s size is 0, please check",
              FILENAME_USB_INTERFACE);
        return false;
    }

    fp = fopen(FILENAME_USB_INTERFACE, "rb");
    if (fp == NULL)
    {
        DEBUG(LOG_ERROR, "filename:%s fopen failed", FILENAME_USB_INTERFACE);
        return false;
    }

    buf = (char *)malloc(len + 1);
    if (!buf)
    {
        DEBUG(LOG_ERROR, "malloc size %lu failed", len + 1);
        fclose(fp);
        return false;
    }
    memset(buf, 0, len);

    fread(buf, 1, len, fp);
    fclose(fp);

    if(decode_usb_interface_auth(buf, info) == false)
    {
        free(buf);
        buf = NULL;
        return false;
    }

    free(buf);
    buf = NULL;

    return true;
}
#endif 

void usbPeripheralPlugAndRemoveEventLogAudit(StorageInfo *info){
    //读取配置文件获取，这个暂不确定从哪读取,临时测试手动写死
    //load_usb_interface_info(info);
    strcpy(info->engine_id, "1");
    strcpy(info->engine_name, "FS");
    info->interface_type = 3;

    //自测调试接口
    print_usb_event_info_log(info);
    printUsbEventInfoHdl(info);
    
    //发送json日志消息
    usb_event_log_json_send(info);
}

/**
 * @brief 获取完整的设备信息
 * @param dev udev设备对象
 * @return 成功返回 0, 失败返回-1
 */
int getDeviceDetailsHdl(struct udev_device *dev, const char *action){
    StorageInfo info;
    memset(&info, 0, sizeof(info));
    if(strcmp(action, "add") == 0){
        info.action = 0; //设备接入
    }else if(strcmp(action, "remove") == 0){
        info.action = 1; //设备拔出
    }

    /* 处理插入事件(带延迟重试机制), 等待系统完成设备挂载初始化, 填充完设备属性信息*/
    usleep(SETTLE_DELAY);

	//1、获取基础设备信息
    if(getBasicCommonDeviceInfo(dev, &info) < 0){
        printf("The Device Node is not mounted, data is incomplete\n");
        return -1;
    }
    
    //2、获取插入设备类型:input设备/net设备/block设备
	if(getDeviceTypeInfo(dev, &info) < 0){
        //事件不处理直接返回主循环
        return -1;
    }

	//3、针对外设存储设备, 获取详细设备属性信息
	const char *subsystem = udev_device_get_subsystem(dev);
	if(strcmp(subsystem, "block") == 0){
        if(strcmp(action, "add") == 0) {
            getUsbDiskStorageMetadata(dev, &info);
        }
	}

    //4、Usb 外设插拔事件日志审计
    usbPeripheralPlugAndRemoveEventLogAudit(&info);
    
    return 0;
}

/**
 * @brief 外设检测主循环
 * @param mon udev监控设备对象
 */
void usb_monitor_loop(struct udev_monitor *mon){  
    fd_set rfds, rset;
    int nready = 0;

    int mon_fd = udev_monitor_get_fd(mon);
    if(mon_fd < 0){
        DEBUG(LOG_ERROR, "udev_monitor_get_fd() error!\n");
        return;
    }
    FD_ZERO(&rfds);
    FD_ZERO(&rset);
    FD_SET(mon_fd, &rset);

    //设置超时时间    
    //struct timeval tv;
    //tv.tv_sec = 3;
    //tv.tv_usec = 0;
    
    while(!g_exit_flag){
        rfds = rset;
        nready = select(mon_fd+1, &rfds, NULL, NULL, NULL);
        if(nready < 0){
			if(errno == EINTR){ //被信号打断，需要继续监听
				continue;
			}
            DEBUG(LOG_ERROR, "select() error!");
            break;
        }
        
        if(FD_ISSET(mon_fd, &rfds)){
            struct udev_device *dev = udev_monitor_receive_device(mon);
            if (!dev) continue;

            // 事件过滤逻辑
            const char *action = udev_device_get_action(dev);
            if((strcmp(action, "add") != 0) && (strcmp(action, "remove") != 0)) {
                udev_device_unref(dev);
                continue;
            }
            
            // 设备有效性检查,虚拟设备直接丢弃掉不去处理
            if (strstr(udev_device_get_syspath(dev), "virtual")) {                
                udev_device_unref(dev);
                continue;
            }
            
            //插拔事件详细处理流程
            getDeviceDetailsHdl(dev, action);
            udev_device_unref(dev);
        } 
    }
    return ;
}

/**
 * @brief 守护进程创建
 * @return 成功返回 0, 失败返回-1
 */
static int create_daemon()
{
    int fd;

    if (g_file_exist(USB_MONITOR_PID))
    {
        DEBUG(LOG_ERROR, "usb_hotplug_monitor pid file %s exit", USB_MONITOR_PID);
        return -1;
    }
    if (daemonize())
    {
        DEBUG(LOG_ERROR, "daemonize failed");
        return -1;
    }

    g_create_path(USB_MONITOR_PID);
    int pid = g_getpid();
    char text[256];
    memset(text, 0x00, sizeof(text));

    fd = g_file_open(USB_MONITOR_PID);
    if (fd == -1)
    {
        DEBUG(LOG_ERROR, "open is failed");
        return -1;
    }
    else
    {
        snprintf(text, sizeof(text), "%d", pid);
        g_file_write(fd, text, strlen(text));
        g_file_close(fd);
    }

    return 0;
}


/* 过滤服务数量 */
#define GREPSERVERNUM   "ps aux|grep -w '%s'|grep -v 'grep'|grep -v 'gdb'|wc -l"
//检测服务 是否为唯一运行的程序
static int check_service_single(const char *server)
{
	FILE *ptr = NULL;
	char buff[256] = {0};

	/* 构造并执行命令 */
	snprintf(buff, 256, GREPSERVERNUM, server);
	ptr = popen(buff, "r");
	if (ptr == NULL) {
		DEBUG(LOG_ERROR, "popen [%s] failed", buff);
		return -1;
	}

	/* 检测服务个数 */
	if (fgets(buff, 256, ptr) != NULL) {
		if (atoi(buff) > 1) {
			DEBUG(LOG_ERROR, "%s server already running, num %d invalid", server, atoi(buff));
			pclose(ptr);
			return -1;
		}
	}

	pclose(ptr);
	return 0;
}

int main(int argc, char *argv[]) {
    /* 检测程序是否单例运行 */
	if (check_service_single(basename(argv[0])) != 0) {
		return -1;
	}

    /* 先添加日志输出,后续更改 */
    debug_level_set(USB_MONITOR_LOG, 4, 0);

    //守护进程创建
	if(argc == 2){
		if(strcmp(argv[1], "-d") == 0){
			if(create_daemon())
			{
				DEBUG(LOG_ERROR,"daemon create is error\n");
				exit(1);
			}
		}
	}

    struct udev *udev = udev_new();
    if (!udev) {
        DEBUG(LOG_ERROR, "Failed to create udev context");
        return -1;
    }

    struct udev_monitor *mon = udev_monitor_new_from_netlink(udev, "udev");
    if (!mon) {
		DEBUG(LOG_ERROR, "Failed to create monitor");
        udev_unref(udev);
        return -1;
    }
    //设置添加外设监控过滤器事件类型    
    //udev_monitor_filter_add_match_subsystem_devtype(mon, "usb", "usb_device");
    udev_monitor_filter_add_match_subsystem_devtype(mon, "block", "disk");
    udev_monitor_filter_add_match_subsystem_devtype(mon, "input", NULL);
    udev_monitor_filter_add_match_subsystem_devtype(mon, "net", NULL);
    
    if (udev_monitor_enable_receiving(mon)) {
        DEBUG(LOG_ERROR, "Failed to start monitoring\n");
        udev_monitor_unref(mon);
        udev_unref(udev);
        return -1;
    }

    signal(SIGINT, signal_handler);
    signal(SIGTERM, signal_handler);

    DEBUG(LOG_DEBUG, "Starting USB Device monitor...");
    usb_monitor_loop(mon);

    udev_monitor_unref(mon);
    udev_unref(udev);
    DEBUG(LOG_DEBUG, "The USB Device monitoring service exits...");
    
    return 0;
}
